NSF ripper Guide Level 3


Level 0   Level 1   Level 2   Level 3   Level 4  

Level 5   Level 6   Level 7   Level 8   Level 9

Level 10   Level 11   Level 12   Level 13   Level 14


LEVEL 3 Sun Electronics Corp. Shanghai II (DPCM)

In Level 3 you're going to learn how to use a disassembler, learn about the NES sound registers and rehashing some methods
used in the last couple of levels.

Go find the disassembler DCC6502. This disassembler has many usefull options for NES and other 6502 CPU's. You can also
use this for FDS disassembling. All you have to do is set the origin and that helps in being able to use any memory
architecture of any 6502 CPU.

First of all you might want to create a folder for NSF compilation. I usually place this folder on the desktop. Within this
directory I place 3 folders and all the utilities I need. These 3 folders should be complete,docs, and work. Any rips that
you are frustrated with you can place in the work folder and come back to them later. All the complete NSF's go in the
complete folder. All your docs you have as reference can go there.

So you get DCC6502 and place this disassembler in that folder. Also you need edit.com. You can find this program somewhere
in windows, just search for it and place it in this folder. You can also get NSFTool at Zophar's Domain in the
Utility/general/Nitendo section. I usually prefer to edit the basics of the header in a hex editor myself. Make sure that
you have nes2nsf in the folder as well. What I usually do is include some emulators in the folder as well. What I do is
make a folder for each one and place the contents in their respective folders. I do this to keep the files down in the main
folder.

Now you get to do some .bat file programming. Don't worry this is really easy and the very basics. Make 2 new text files in
the main folder and rename the first one asm.bat and the second one edit.bat. After you have done this right click on
asm.bat and click edit. So you have a blank note pad. What you type here is DCC6502 -h -n -o8000 filename.DMP >>
filename.asm . This is your bat file to run the disassembler DCC6502 based on what you typed in the .bat file. Next you
right click on edit.bat and type in EDIT filename.asm and you're done. You have to change the file name all the time
depending on what game you're messing with. I usually rename them in DOS format with 8 characters or less to make it easy.

The options was set on the .bat for DCC6502 are as follows. -h is hex output and you need this there because it tells you
the bytes of the opcode and operation. -n is Nintendo register commenting and is useful in knowing what areas of code do
what. If you see a write to $2006 then more then likely this is not a sound driver area. And the next one -0xxxx is what you
set the origin of the disassembly output. If the start of the code is CPU address $8000 then you set it at -o8000. With FDS
rips you can set the origin at $6000 since that is where PRG RAM starts. After all this is the file you want to disassemble
and last but not least is >> and after that is the disassembly and you should name the extension .asm.

Now comes the time to learn some NES sound registers. $4015 is the sound enable register and turns on and off the sound
channels. There is 5 channels in the NES. You have to write a byte to $4015 to enable or disable certain channels. If you
are familiar with the bits of a hex byte then this should make sense.

First of all when you designate a value to the A register you are turning ON/OFF the sound register. A91F8D1540 The following routine. A9 1F LDA #$1F When you have 1F in the A register and then convert this value to binary you get 00011111 8D 15 40 STA $4015 Store your value in A that is 1F to address 4015. 4015 When you set bits---abcde(00011111)You're actually turning all the 5 channels ON.

By the way here is the 5 channels. Channels 1(e) Square #1 2(d) Square #2 3(c) Triangle 4(b) Noise 5(a) DPCM (Delta Modulation)

Now I will list the sound registers and what channel they are associated with.

Square 1/Square 2

$4000/4 ddle nnnn duty, loop env/disable length, env disable, vol/env period $4001/5 eppp nsss enable sweep, period, negative, shift $4002/6 pppp pppp period low $4003/7 llll lppp length index, period high

Triangle

$4008 clll llll control, linear counter load $400A pppp pppp period low $400B llll lppp length index, period high

Noise

$400C --le nnnn loop env/disable length, env disable, vol/env period $400E s--- pppp short mode, period index $400F llll l--- length index

DMC

$4010 il-- ffff IRQ enable, loop, frequency index $4011 -ddd dddd DAC $4012 aaaa aaaa sample address $4013 llll llll sample length

Common $4015 ---d nt21 length ctr enable: DMC, noise, triangle, pulse 2, 1 $4017 fd-- ---- 5-frame cycle, disable frame interrupt

Status (read)

$4015 if-d nt21 DMC IRQ, frame IRQ, length counter statuses

As you can see these are the sound channels. Don't panic you don't have to absorb all of this right away. Just be kinda
familiar with them.


Now we are going to do the rip after all that. First of all look at the .ini file for nes2nsf. Set bit 0F to 1 and run the
program. Load up Shanghai 2. You will see a display come up and it will tell you it's a write to 4015, this is a part of the
program I couldn't translate because I don't have the source yet. Check up above for a very vague description of 4015.
Everytime nes2nsf stops you will see a menu and it will tell you the CPU address location of the write each time nes2nsf
runs into one in the PRG.

Now go ahead and use nes2nsf to rip a NSF from Shanghai 2. You will notice that the menu comes up with option 0F set. You
will notice that a write to $4015 is found at the following CPU addresses $800C,$8030,$8796,$879B. If you want to find these
in the NSF use the following formula. -8000 +80 = NSF Offset in a hex editor. You will see the bytes 8D1540.

You will notice that the bank 002 is ripped with the file name Shanghai 2(J)_002.nsf. Try to play the NSF and it won't play
at all. So we should disassemble the bank and see what the problem is. First you have to remove the NSF header in order to
disassemble the bank. The header is in the range of 0h - 7Fh, Don't remove 80h and past that offset. Do this with a hex
editor. Rename the file without the header shang.DMP . Change the asm.bat file contents to DCC6502 -h -n -o8000 >>shang.asm.
And change edit.bat contents to Edit shang.asm and click on the asm.bat, if you don't have any errors then you did it. Wait
for a second or 2 then click on edit.bat and you should see a DOS text window come up with the banks disassembly.

You should see the following code if you did the disassembly right.

8000 : 02 db $02 ; invalid op 8001 : 4C 6E 81 JMP $816E ; 8004 : 4C A6 80 JMP $80A6 ; 8007 : 4C 0A 80 JMP $800A ; 800A : A9 1F LDA #$1F ; 800C : 8D 15 40 STA $4015 ; Sound control 800F : A9 00 LDA #$00 ; 8011 : 8D 10 40 STA $4010 ; PCM Control reg.

Remember the Level 1 with the load/init/play addresses are 8000/8003/8000 and about the same as level 2 with the JMP's as
well except you don't have to do the bootstrap code. However the .db(data byte) at CPU address $8000 is throwing the order
of the JMP's off. That byte is actually the bank number, however moving on. So you have JMP's at $8001,$8004,$8007. Change
the load/init/play addresses in the header to 8000/8004/8001 and load the NSF up and wow it plays. However you don't hear the
DPCM and I will get to that problem next. Also remember to look at the addresses that nes2nsf gave you for the writes to
$4015 and look at some of the other sound writes and look at the description above and you can even check out the APU
reference. This will help you in the long run so you should do it.

So you have a rip that works and is missing the DPCM. This rip would be labeled as Incomplete in the composer info in the
header if you could not fix it. However I do have a solution. First rename the NSF rip to shang.nsf to keep it from being
overwritten because you're going to use nes2nsf again.

You might be somewhat familiar with mappers and this game is mapper 2. Mapper 2 swaps banks at $8000 - $BFFF and the bank
at $C000 - $FFFF is hardwired and never changes. The hardwired bank comes from the last PRG bank in the rom right before the
CHR(Character ROM) if the rom has any. This last bank is important for DPCM because DPCM samples can only be placed in CPU
memory $C000 - $FFF9. So you have to find this bank and append it to the NSF for it to pick up the DPCM samples.

I have alittle trick to use here. What you're going to do is use nes2nsf again and change the .inf settings. Change bit 0 to
0 because you don't need the header because you are adding a bank on to the NSF at the end. And change bit 4 to 0 because you
want nes2nsf to split the entire rom into banks. Now run the program. Make sure you change them back to the defaults when
you're done so that you don't forget.

I use a hex editor to join files so you should probably do what I do and use Hex Workshop. If not you will have to use
another hex editor that has that option or a file split/join utility.

Take a look at what nes2nsf outputted and see that you have 8 files that are numbered 000-007. Take file 007 because this is
the last bank in the ROM, this rom has no CHR. Load up the Shanghai NSF that you ripped earlier and load up bank 007 and
append bank 007 to the end of the NSF. Load the NSF in a player and presto you have DPCM and it works and sounds good.
Sunsoft has real good tunes.

Now you have a couple things left to do. You must edit the header. Fill in the Name of the game,Composer(if you can't find
his/her name or fill in a ? mark). Also you have to arrange the tunes. Find some free space in the rom. Free space is
usually a real large chunk of 00's or FF's. I have a recommended spot in the NSF to place the tune arrangement code. That's
3530h Offset in the NSF. You want to figure out what the CPU address is for that offset. Once again I have a formula. Offset
-80 +8000 = CPU address. Place this address in the header in the init address. Now you do the tune arrangement code. This
time it's much simpler and no bootstrap. Place this code at offset 3530h in the NSF.

The CPU address answer is $B4BO and put that in the header in the init address section. Remember to flip the address bytes.

$B4B0 AA TAX $B4B1 BD B7 B3 LDA $B4B7,X ; point to the tune index $B4B4 4C 04 80 JMP $8004 ; jump to init .db tune numbers here ; arrange them yourself :)

I shall show you how to optimize this rip soon. This bank joining will be real usefull one day.